 package com.gmrz.uaf.crypto.internal.algos;
 
 import com.gmrz.uaf.crypto.CryptoConstants;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.DERInteger;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import java.io.IOException;
import java.math.BigInteger;
import java.security.*;
 
 public class UAFAuthAlgECDSARaw extends UAFAuthAlg
 {
   private static final Logger logger = LogManager.getLogger(UAFAuthAlgECDSARaw.class);

   private Provider bouncyCastleProvider;
 
   public UAFAuthAlgECDSARaw(CryptoConstants.UAFAlgSign authAlgorithmSuite)
   {
     super(authAlgorithmSuite);
   }
 
   public boolean init()
   {
     this.bouncyCastleProvider = Security.getProvider("BC");
 
     boolean bouncyCastleAvailable = this.bouncyCastleProvider != null;
     boolean signAlgoAvailable = Security.getAlgorithms("Signature").contains(this.authAlgorithmSuite.getSignatureAlgo());
 
     return (bouncyCastleAvailable) && (signAlgoAvailable);
   }
 
   public boolean verifySignature(PublicKey publicKey, byte[] signedData, byte[] signature)
     throws GeneralSecurityException
   {
     logger.info("ECDSARAW verifySignature");
     long start = System.currentTimeMillis();
     Signature sig = Signature.getInstance(this.authAlgorithmSuite.getSignatureAlgo(), new BouncyCastleProvider());
 
     sig.initVerify(publicKey);
     sig.update(signedData);
 
     if ((signature == null) || (signature.length != 64)) {
       throw new GeneralSecurityException("ECDSA Raw Signature is not of the desired length."); }
       byte[] r = new byte[32];
     byte[] s = new byte[32];
     System.arraycopy(signature, 0, r, 0, 32);
     System.arraycopy(signature, 32, s, 0, 32);
     BigInteger[] rs = new BigInteger[2];
     rs[0] = new BigInteger(1, r);
     rs[1] = new BigInteger(1, s);
     ASN1EncodableVector v = new ASN1EncodableVector();
     v.add(new DERInteger(rs[0]));
     v.add(new DERInteger(rs[1]));
     byte[] derEncoded;
     try { derEncoded = new DERSequence(v).getEncoded();
     } catch (IOException e) {
       throw new GeneralSecurityException(e);
     }
     logger.debug("UAFAuthAlgECDSARaw verifySignature time :"+(System.currentTimeMillis()-start)+" ms");
     return sig.verify(derEncoded);
   }
 }
